# -*- coding: utf-8 -*-
# @File     : api.py
# @Author   : bingjia
# @Time     : 2020/7/27 16:54
# @Desc     : user视图集

import uuid

from django.db.utils import IntegrityError
from django.contrib.auth import get_user_model
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
from easy_thumbnails.source_generators import pil_image

from ..auth import signals
from ..auth.validators import RegisterValidator
from ..auth.services import make_auth_response_data
from ..auth.services import is_user_already_registered
from ..auth.services import get_user_by_username_or_email

from ..base.api import response
from ..base.api import exceptions as exc
from ..base.api.viewsets import ModelViewSet
from ..base.api.utils.decorators import list_route, detail_route

from . import models
from . import services
from . import validators
from . import pagination
from . import throttling
from . import serializers
from . import permissions


class UsersViewSet(ModelViewSet):
    """
    用户视图
    """
    queryset = models.User.objects.all()
    "验证"
    validator_class = validators.UserValidator
    "分页"
    pagination_class = pagination.UserPagination
    "序列化"
    serializer_class = serializers.UserSerializer
    "权限"
    permission_classes = (permissions.UserPermission,)
    "节流"
    throttle_classes = (throttling.UserDetailRateThrottle, throttling.UserUpdateRateThrottle)

    def list(self, request, *args, **kwargs):
        raise exc.MethodNotAllowed(method='GET')

    def create(self, request, *args, **kwargs):
        raise exc.MethodNotAllowed(method='POST')

    def retrieve(self, request, *args, **kwargs):
        """
        单个（pk用户数据）
        """
        user_object = get_object_or_404(self.get_queryset(), **kwargs)
        self.check_permissions(request, 'retrieve', user_object)
        serializer = self.get_serializer(user_object)
        return response.Ok(serializer.data)

    def destroy(self, request, *args, **kwargs):
        """
        删除用户
        """
        user_object = get_object_or_404(self.get_queryset(), **kwargs)
        self.check_permissions(request, 'destroy', user_object)
        user_object.delete()
        return response.NoContent()

    @list_route(methods=["POST"])
    def change_avatar(self, request, pk=None):
        """
        更换头像
        """
        self.check_permissions(request, "change_avatar", None)

        avatar = request.FILES.get('avatar', None)

        if not avatar:
            raise exc.ValidationError(_("Incomplete arguments"))

        try:
            pil_image(avatar)
        except Exception:
            raise exc.ValidationError(_("Invalid image format"))

        request.user.photo = avatar
        request.user.save(update_fields=["photo"])
        user_data = self.admin_serializer_class(request.user).data

        return response.Ok(user_data)

    @list_route(methods=["GET"])
    def by_username(self, request):
        """
        通过用户名查找用户
        """
        username = request.query_params.get("username", None)
        self.check_permissions(request, 'by_username', None)
        return self.retrieve(request, username=username)

    @list_route(methods=["GET"])
    def by_pk(self, request):
        """
        通过id查找用户
        """
        pk = request.query_params.get("pk", None)
        self.check_permissions(request, 'by_username', None)
        return self.retrieve(request, pk=pk)

    @list_route(methods=["POST"])
    def password_recovery(self, request, pk=None):
        """
        恢复密码
        """
        username_or_email = request.data.get('username', None)
        self.check_permissions(request, "password_recovery", None)

        if not username_or_email:
            raise exc.ParseError(_("Invalid username or email"))

        user = get_user_by_username_or_email(username_or_email)
        user.token = str(uuid.uuid4())
        user.save(update_fields=["token"])

        # email = mail_builder.password_recovery(user, {"user": user})
        # email.send()

        return response.Ok({"detail": _("Mail sended successful!")})

    @list_route(methods=["POST"])
    def change_password_from_recovery(self, request, pk=None):
        """
        修改密码(恢复密码)
        """
        self.check_permissions(request, "change_password_from_recovery", None)

        validator = validators.RecoveryValidator(data=request.data, many=False)
        if not validator.is_valid():
            raise exc.ValidationError(_("Token is invalid"))

        try:
            user = models.User.objects.get(token=validator.data["token"])
        except models.User.DoesNotExist:
            raise exc.ValidationError(_("Token is invalid"))

        user.set_password(validator.data["password"])
        user.token = None
        user.save(update_fields=["password", "token"])

        return response.NoContent()

    @detail_route(methods=["POST"])
    def change_password(self, request, pk=None):
        """
        修改密码
        """
        services.is_same_of_token_and_pk(request.user, self.queryset, pk)
        self.check_permissions(request, "change_password", None)

        current_password = request.data.get("current_password")
        password = request.data.get("password")

        if not current_password and request.user.password:
            raise exc.ValidationError(_("Current password parameter needed"))

        if not password:
            raise exc.ValidationError(_("New password parameter needed"))

        if len(password) < 6:
            raise exc.ValidationError(_("Invalid password length at least 6 charaters needed"))

        if current_password and not request.user.check_password(current_password):
            raise exc.ValidationError(_("Invalid current password"))

        request.user.set_password(password)
        request.user.save(update_fields=["password"])
        return response.NoContent()


class UsersMessage(ModelViewSet):
    """
    用户消息视图
    """
    def create(self, request, *args, **kwargs):
        """
        新增
        """
    def list(self, request, *args, **kwargs):
        """
        群查
        """
    def retrieve(self, request, *args, **kwargs):
        """
        单查
        """
    def destroy(self, request, *args, **kwargs):
        """
        删除
        """
    @list_route(methods=["POST"])
    def all_read(self, request, *args, **kwargs):
        """
        全部已读
        """

    @list_route(methods=["POST"])
    def all_delete(self, request, *args, **kwargs):
        """
        全部删除
        """


class UserAdminViewSet(ModelViewSet):
    """
    管理员用户视图
    """
    queryset = models.User.objects.all()
    "验证"
    validator_class = validators.UserAdminValidator
    "序列化"
    serializer_class = serializers.UserAdminSerializer
    "权限"
    permission_classes = (permissions.UserAdminPermission,)

    def _parse_data(self, data: dict, *, cls):
        """
        解析用户数据并返回用户数据
        """
        validator = cls(data=data)
        if not validator.is_valid():
            raise exc.RequestValidationError(validator.errors)
        return validator.data

    def _user_register(self, username: str, password: str, email: str, full_name: str):
        """
        检测是否注册，并完成注册
        """
        is_registered, reason = is_user_already_registered(username=username, email=email)
        if is_registered:
            raise exc.ValidationError(reason)

        user_model = get_user_model()
        user = user_model(username=username,
                          email=email,
                          full_name=full_name,
                          read_new_terms=True)
        user.set_password(password)
        try:
            user.save()
        except IntegrityError:
            raise exc.ValidationError(_("User is already registered."))

        signals.user_registered_signal.send(sender=user.__class__, user=user)
        return user

    def create(self, request, *args, **kwargs):
        """
        单增注册用户
        """
        self.check_permissions(request, 'create', None)
        try:
            data = self._parse_data(request.data, cls=RegisterValidator)
            user = self._user_register(**data)
        except exc.ParseError as e:
            raise exc.BadRequest(e.detail)

        data = make_auth_response_data(user)

        return response.Created(data)

    def list(self, request, *args, **kwargs):
        """
        群查（用户数据）
        """
        self.check_permissions(request, 'list', None)
        user_object_list = self.get_queryset()
        page = self.paginate_queryset(user_object_list)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        else:
            serializer = self.get_serializer(user_object_list, many=True)

        return response.Ok(serializer.data)




